import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

/**
 * Created with IntelliJ IDEA.
 * Description:
 */

class MyTimerTask{
    // 表示任务执行的时间
    private long time;
    // 表示要执行的任务
    private Runnable task;
    // 构造函数，初始化任务和执行时间
    public MyTimerTask(Runnable task,long time){
      this.time = time;
      this.task =task;
    }
    // 获取任务执行的时间
    public long getTime(){
        return this.time;
    }
    // 获取要执行的任务
    public Runnable getTask(){
        return this.task;
    }
}

class MyTimer {
    // 使用优先队列存储定时任务，按任务执行时间排序
    private PriorityQueue<MyTimerTask> queue =new PriorityQueue<>(
            ( o1, o2)->Long.compare(o1.getTime(),o2.getTime()));
    // 安排任务在指定延迟后执行
    public void schedule(Runnable task,long delay){
        synchronized (queue){
            queue.offer(new MyTimerTask(task,System.currentTimeMillis()+delay));
            queue.notify();
        }
    }

    // 构造函数，启动一个线程来处理定时任务
    public MyTimer(){
        Thread thread =new Thread(()->{
          try {
                  // 无限循环，等待并执行任务
                  while (true){
                      Runnable taskToExecute =null;
                      synchronized (queue){
                      // 如果队列为空，等待任务被添加
                      while (queue.isEmpty()){
                          queue.wait();
                      }
                      // 获取队列头部的任务
                      MyTimerTask task =queue.peek();
                      // 如果当前时间小于任务执行时间，等待直到任务执行时间
                      if(System.currentTimeMillis()<task.getTime()){
                          queue.wait(task.getTime()-System.currentTimeMillis());
                      }else {
                           // 否则，取出任务
                           taskToExecute = task.getTask();
                          queue.poll();
                      }
                  }
                  // 执行任务
                  if (taskToExecute!=null){
                      taskToExecute.run();
                  }
              }
          } catch (InterruptedException e) {
              throw new RuntimeException(e);
          }
        });
        thread.start();
    }
}

public class Demo5 {
    public static void main(String[] args) {
        MyTimer myTimer =new MyTimer();
        Thread t1 =new Thread(()->{
            myTimer.schedule(()->{
                System.out.println("hello 3000");
            },3000);
        });
        Thread t2 =new Thread(()->{
            myTimer.schedule(()->{
                System.out.println("hello 2000");
            },2000);
        });
        Thread t3 =new Thread(()->{
            myTimer.schedule(()->{
                System.out.println("hello 1000");
            },1000);
        });
        t1.start();
        t2.start();
        t3.start();
    }
}
